/*
* JavaCL - Java API and utilities for OpenCL
* http://javacl.googlecode.com/
*
* Copyright (c) 2009-2015, Olivier Chafik (http://ochafik.com/)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Olivier Chafik nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.nativelibs4java.opencl.demos.sobelfilter;
import org.bridj.JNI;
import javax.swing.*;
import com.nativelibs4java.opencl.*;
import com.nativelibs4java.opencl.util.*;
import com.nativelibs4java.opencl.demos.SetupUtils;
import com.nativelibs4java.util.Pair;
import java.awt.image.*;
import java.io.*;
import org.bridj.Platform;
import org.bridj.Pointer;
import static org.bridj.Pointer.*;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import java.awt.FileDialog;
public class SobelFilterDemo {
static File chooseFile() {
if (Platform.isMacOSX()) {
FileDialog d = new FileDialog((java.awt.Frame)null);
d.setMode(FileDialog.LOAD);
d.show();
String f = d.getFile();
if (f != null)
return new File(new File(d.getDirectory()), d.getFile());
} else {
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
return chooser.getSelectedFile();
}
return null;
}
public static void main(String[] args) {
try {
SetupUtils.failWithDownloadProposalsIfOpenCLNotAvailable();
File imageFile = chooseFile();
if (imageFile == null)
return;
BufferedImage image = ImageIO.read(imageFile);
int width = image.getWidth(), height = image.getHeight();
//int step = 32;
// image = image.getSubimage(0, 0, (width / step) * step, (height / step) * step);
//image = image.getSubimage(0, 0, 512, 512);//(width / step) * step, (height / step) * step);
JFrame f = new JFrame("JavaCL Sobel Filter Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SobelFilterDemo demo = new SobelFilterDemo();
Pair<BufferedImage, BufferedImage> imgs = demo.computeSobel(image);
f.getContentPane().add("Center",
//new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
// new JScrollPane(new JLabel(new ImageIcon(image))),
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
new JScrollPane(new JLabel(new ImageIcon(imgs.getFirst()))),
new JScrollPane(new JLabel(new ImageIcon(imgs.getSecond())))
) {/**
*
*/
private static final long serialVersionUID = 8267014922143370639L;
{
setResizeWeight(0.5);
}}
//)
);
f.pack();
f.setVisible(true);
} catch (Throwable th) {
th.printStackTrace();
SetupUtils.exception(th);
}
}
CLContext context;
CLQueue queue;
SimpleSobel sobel;
ReductionUtils.Reductor<Float> floatMinReductor;
public SobelFilterDemo() throws IOException, CLBuildException {
context = JavaCL.createBestContext();
queue = context.createDefaultQueue();
sobel = new SimpleSobel(context);
floatMinReductor = ReductionUtils.createReductor(context, ReductionUtils.Operation.Max, OpenCLType.Float, 1);
}
public static int roundUp(int group_size, int global_size)
{
int r = global_size % group_size;
return r == 0 ? global_size : global_size + group_size - r;
}
public Pair<BufferedImage, BufferedImage> computeSobel(BufferedImage img) throws IOException, CLBuildException {
int width = img.getWidth(), height = img.getHeight();
int dataSize = height * width;
Pointer<Integer> pixels = Pointer.pointerToInts(img.getRGB(0, 0, width, height, null, 0, width));
CLImage2D inputImage = context.createImage2D(CLMem.Usage.Input, new CLImageFormat(CLImageFormat.ChannelOrder.ARGB, CLImageFormat.ChannelDataType.UnsignedInt8), width, height, width * 4, pixels.getBuffer(), true);
//CLImage2D inputImage = context.createImage2D(CLMem.Usage.Input, img, false);
CLBuffer<Float>
gradients = context.createBuffer(CLMem.Usage.InputOutput, Float.class, dataSize),
directions = context.createBuffer(CLMem.Usage.InputOutput, Float.class, dataSize);
CLEvent evt = sobel.simpleSobel(queue,
inputImage,
width,
height,
gradients,
directions,
new int[] { width, height },
null//new int[] { 1, 1 }
);
//queue.finish();
//float[] test = new float[1000];
//gradients.read(queue).get(test);
float gradientMax = floatMinReductor.reduce(queue, gradients, dataSize, 32, evt).get();
float dirMax = floatMinReductor.reduce(queue, directions, dataSize, 32, evt).get();
//CLEvent.waitFor(evtGradMax, evtDirMax);
CLBuffer<Integer> gradientPixels = context.createBuffer(CLMem.Usage.Output, Integer.class, dataSize);
CLBuffer<Integer> directionPixels = context.createBuffer(CLMem.Usage.Output, Integer.class, dataSize);
//CLEvent evtGrad =
sobel.normalizeImage(queue, gradients, gradientMax, (CLBuffer)gradientPixels, new int[] { dataSize }, null);
//CLEvent evtDir =
sobel.normalizeImage(queue, directions, dirMax, (CLBuffer)directionPixels, new int[] { dataSize }, null);
queue.finish();
BufferedImage gradientsImage = getRowsOrderImage(queue, gradientPixels, width, height);//, evtGrad);
BufferedImage directionsImage = getRowsOrderImage(queue, directionPixels, width, height);//, evtDir);
return new Pair<BufferedImage, BufferedImage>(gradientsImage, directionsImage);
}
static BufferedImage getRowsOrderImage(CLQueue queue, CLBuffer<Integer> buffer, int width, int height, CLEvent... eventsToWaitFor) {
queue.finish();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int[] pixels = buffer.read(queue, eventsToWaitFor).getInts(width * height);
img.setRGB(0, 0, width,height, pixels, 0, width);
return img;
}
}